home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / threads / ThreadsKillWorld.c < prev    next >
C/C++ Source or Header  |  1991-06-11  |  7KB  |  288 lines

  1. /*
  2.  * ThreadsKillWorld.c
  3.  *
  4.  * PCR System termination -- exit, panic, ThreadsTermination.
  5.  *
  6.  * Demers, December 13, 1990 10:50:00 am PST
  7.  */
  8.  
  9. #include "xr/Errno.h"
  10. #include "xr/ThreadsBackdoor.h"
  11. #include "xr/ThreadsPrivate.h"
  12. #include "xr/ThreadsMsgPrivate.h"
  13. #include "xr/ThreadsSignalsPrivate.h"
  14.  
  15. #include <sys/types.h>
  16. #include <sys/ipc.h>
  17. #include <sys/sem.h>
  18. #include <sys/signal.h>
  19. #include <sys/wait.h>
  20.  
  21.  
  22. #define DEBUG_CLEANUP    0
  23.  
  24. /*
  25.  * panic behavior control
  26.  */
  27.  
  28. bool XR_suspendOnPanic = TRUE;
  29.  
  30. bool
  31. XR_GetSuspendOnPanic()
  32. {
  33.     return XR_suspendOnPanic;
  34. }
  35.  
  36.  
  37. bool
  38. XR_SetSuspendOnPanic(suspend)
  39. {
  40.     bool oldValue = XR_suspendOnPanic;
  41.     XR_suspendOnPanic = suspend;
  42.     return oldValue;
  43. }
  44.  
  45.  
  46. #define MAX_PASSES    6
  47. #define PASS_WAIT_USEC    200000
  48.  
  49. #define PANIC_STATUS    0x543210ff
  50.  
  51.  
  52. /*
  53.  * Kill all siblings. 
  54.  * Try to do this with XR_SIG_EXIT so they can die gracefully.
  55.  * If that fails, use SIGKILL.
  56.  *
  57.  * This proc should be called with all signals blocked.
  58.  */
  59. static void
  60. XR_KillSiblings (status)
  61. {
  62.     int i, pid, mypid, passNum, sigToSend;
  63.     bool gotOne;
  64.     extern int getpid(), kill();
  65.  
  66.     mypid = getpid();
  67.     for( ((passNum = 1), (gotOne = TRUE))
  68.         ; ((passNum <= MAX_PASSES) && gotOne)
  69.         ; passNum++
  70.     ) {
  71.         gotOne = FALSE;
  72.         sigToSend = ((passNum < MAX_PASSES) ? XR_SIG_EXIT : SIGKILL);
  73.         for( i = 0; i < XR_sysArea->sa_numIOP; i++ ) {
  74.             pid = XR_sysArea->sa_iope[i].iope_pid;
  75.             if( (pid != 0) && (pid != mypid) ) {
  76.                 if( kill(pid, sigToSend) >= 0 ) gotOne = TRUE;
  77.             }
  78.         }
  79.         for( i = 0; i < XR_sysArea->sa_numVP; i++ ) {
  80.             pid = XR_sysArea->sa_vpe[i].vpe_pid;
  81.             if( (pid != 0) && (pid != mypid) ) {
  82.                 if( kill(pid, sigToSend) >= 0 ) gotOne = TRUE;
  83.             }
  84.         }
  85.         pid = XR_sysArea->sa_dbpid;
  86.         if( (pid != 0) && (pid != mypid) ) {
  87.             if( kill(pid, sigToSend) >= 0 ) gotOne = TRUE;
  88.         }
  89.         if( gotOne ) {
  90.             (void)XR_SpinStep(PASS_WAIT_USEC*passNum);
  91.             while( wait3(NIL, (WNOHANG|WUNTRACED), NIL) > 0 ) {}
  92.         }
  93.     }
  94. }
  95.  
  96.  
  97. /*
  98.  *
  99.  * Exported to ThreadsTermination.h
  100.  *
  101.  * Discard all PCR resources we know about.
  102.  *
  103.  * XR_FinalCleanup should be called with no threads running,
  104.  *   and on Unix stack ...
  105.  *
  106.  * The preferred way to do this is
  107.  *
  108.  *     XR_longjmp(&XR_finalCleanupJmpBuf, status|0x80000000)
  109.  *
  110.  * allowing the call to be made from ThreadsInit.c
  111.  */
  112.  
  113.  
  114. /* static */ struct XR_MLRep XR_cleanupProcsLock;
  115.  
  116. typedef struct XR_CleanupProcEltRep {
  117.     struct XR_CleanupProcEltRep * cpe_next;
  118.     void (**cpe_proc)();
  119.     XR_Pointer cpe_clientData;
  120. } * XR_CleanupProcElt;
  121.  
  122. #define N_FREE_ELTS 4
  123.  
  124. /* static */ XR_CleanupProcElt XR_cleanupProcList = NIL;
  125. /* static */ struct XR_CleanupProcEltRep XR_cleanupProcElts[N_FREE_ELTS];
  126. /* static */ int XR_freeCleanupProcElts =
  127.     ( (sizeof XR_cleanupProcElts) / (sizeof XR_cleanupProcElts[0]) );
  128.  
  129. int
  130. XR_RegisterTerminationCleanupProc(proc, clientData)
  131.     void (**proc)();
  132.     XR_Pointer clientData;
  133. {
  134.     XR_CleanupProcElt cpe;
  135.  
  136.     if( XR_currThread != NIL ) {
  137.         XR_MonitorEntry(&XR_cleanupProcsLock);
  138.         cpe = (XR_CleanupProcElt)XR_malloc( sizeof *cpe );
  139.         if( cpe == NIL ) { XR_SetErrno(ENOMEM); return (-1); }
  140.     } else {
  141.         if( XR_freeCleanupProcElts <= 0 )
  142.             XR_Panic("RegisterTerminationCleanupProc: out of memory");
  143.         XR_freeCleanupProcElts -= 1;
  144.         cpe = &XR_cleanupProcElts[XR_freeCleanupProcElts];
  145.     }
  146.     cpe->cpe_proc = proc;
  147.     cpe->cpe_clientData = clientData;
  148.     cpe->cpe_next = XR_cleanupProcList;
  149.     XR_cleanupProcList = cpe;
  150.     if( XR_currThread != NIL ) XR_MonitorExit(&XR_cleanupProcsLock);
  151.     return 0;
  152. }
  153.  
  154.  
  155. struct XR_JmpBufRep XR_finalCleanupJmpBuf;
  156.  
  157. void
  158. XR_FinalCleanup(xStatus)
  159.     int xStatus;
  160. {
  161.     XR_CleanupProcElt cpe;
  162.  
  163.     for( cpe = XR_cleanupProcList; cpe != NIL; cpe = cpe->cpe_next ) {
  164.         if( (cpe->cpe_proc != NIL) && ((*(cpe->cpe_proc)) != NIL) ) {
  165.             (**(cpe->cpe_proc))(cpe->cpe_clientData);
  166.         }
  167.     }
  168.     XR_CleanUpSharedMem(); /* ??? put this on list ??? */
  169.     _exit( ((xStatus << 1) >> 1) );
  170. }
  171.  
  172.  
  173. /*
  174.  * Wait for an exit signal ... used when pausing for panic.
  175.  */
  176. static void
  177. XR_WaitForExitSignal()
  178. {
  179.    extern unsigned XR_exitSigs[];
  180.    unsigned mask, signum;
  181.    unsigned *sigp;
  182.  
  183.    mask = sigblock(0);
  184.    sigp = XR_exitSigs;
  185.    while( (signum = *sigp++) != 0 ) {
  186.        mask &= (~ (sigmask(signum)) );
  187.    }
  188.    (void)sigpause(mask);
  189. }
  190.  
  191.  
  192.  
  193. /*
  194.  * ExitWorld
  195.  *
  196.  * This can be called from thread or signal handler,
  197.  *   on VP or IOP, sometimes recursively.
  198.  * It has to check out the state to be sure it does the
  199.  *   right thing.
  200.  */
  201.  
  202. extern int XR_localExitCnt;    /* PER PROCESSOR */
  203.  
  204. void
  205. XR_ExitWorld (status)
  206.     int status;
  207. {
  208.     (void)sigblock(-1);
  209.  
  210.     /* Make sure that the garbage collector hasn't protected     */
  211.     /* any pages we care about.                  */
  212.     if (XR_vpe != NIL) XR_ShutDownVD();
  213.  
  214.     if( XR_localExitCnt > 0 ) /* recursive entry */ return;
  215.     XR_localExitCnt += 1;
  216.  
  217.     if( XR_sysArea != NIL ) {
  218.         /*
  219.          * execute mutex protocol so kill is done only once.
  220.          */
  221.         if( XR_TestAndSet(&(XR_sysArea->sa_terminating.psl_locked)) == 0 ) {
  222.             /* got the lock, I'm responsible for doing the kill ... */
  223.             if( XR_currThread != NIL ) {
  224.                 /* inhibit preemption if running in a thread */
  225.                 /* (not *really* necessary because of sigblock above) */ 
  226.             XR_currThread->t_swStat = XR_SWSTAT_DONT_PREEMPT;
  227.         }
  228.             XR_sysArea->sa_terminationStatus = status;
  229.             XR_KillSiblings();
  230.         } else {
  231.             /* failed to get lock, somebody else will do kill ... */
  232.             XR_SpinStep(100000); /* wait for terminationStatus to appear */
  233.             _exit( XR_sysArea->sa_terminationStatus );
  234.         }
  235.     } else {
  236.         /*
  237.          * there's only one Unix process, no mutex needed
  238.          */
  239.         ;
  240.     }
  241.  
  242.     /*
  243.      * Claim: exactly one process gets to this point ...
  244.      */
  245.     if( (status == PANIC_STATUS) && XR_GetSuspendOnPanic() ) {
  246.         XR_WaitForExitSignal();
  247.     }
  248.     XR_longjmp(&XR_finalCleanupJmpBuf, (status|0x80000000) );
  249.     /*NOTREACHED*/
  250. }
  251.  
  252.  
  253.  
  254. void
  255. XR_KillWorld ()
  256. {
  257.     XR_ExitWorld(-1);
  258. }
  259.  
  260.  
  261. int (*XR_BKS_Main_Proc)() = NIL;
  262.  
  263. void
  264. XR_Panic(msg)
  265.     char *msg;
  266. {
  267.     int i;
  268.     int savedErrno;
  269.  
  270.     /* block all interrupts */
  271.     (void)sigblock(-1);
  272.     /* save errno */
  273.     savedErrno = XR_GetErrno();    /* works on VP or IOP! */
  274.     /* save panic message */
  275.     if( XR_sysArea != NIL ) {
  276.             XR_sysArea->sa_panicMsg = msg;
  277.     }
  278.     XR_ConsoleMsg("\n%? PANIC %s\n", msg);
  279.     XR_ConsoleMsg("%? PANIC pid %d\n", getpid());
  280.     XR_ConsoleMsg("%? PANIC errno %d\n\n", savedErrno );
  281.     /* PANIC hole for SSU Backstop */
  282.         if( XR_BKS_Main_Proc != NIL ) {
  283.             (*XR_BKS_Main_Proc)();
  284.         }
  285.     /* "halt" */
  286.     XR_ExitWorld( PANIC_STATUS );
  287. }
  288.